home *** CD-ROM | disk | FTP | other *** search
- .model large
-
- ;EXECSWAP.ASM
- ; Swap memory and exec another program
- ; Copyright (c) 1988 TurboPower Software
- ; May be used freely as long as due credit is given
- ;-----------------------------------------------------------------------------
- ;DATA SEGMENT BYTE PUBLIC
- .data
- EXTRN _BytesSwapped:DWORD ;Bytes to swap to EMS/disk
- EXTRN _EmsAllocated:BYTE ;True when EMS allocated for swap
- EXTRN _FileAllocated:BYTE ;True when file allocated for swap
- EXTRN _EmsHandle:WORD ;Handle of EMS allocation block
- EXTRN _FrameSeg:WORD ;Segment of EMS page frame
- EXTRN _FileHandle:WORD ;Handle of DOS swap file
- EXTRN _SwapName:BYTE ;ASCIIZ name of swap file
- EXTRN _PrefixSeg:WORD ;Base segment of program
- ;DATA ENDS
- ;-----------------------------------------------------------------------------
- ;CODE SEGMENT BYTE PUBLIC
- .code
- ; ASSUME CS:CODE,DS:DATA
- PUBLIC EXECWITHSWAP, _FIRSTTOSAVE
- PUBLIC ALLOCATESWAPFILE, DEALLOCATESWAPFILE
- PUBLIC EMSINSTALLED, EMSPAGEFRAME
- PUBLIC ALLOCATEEMSPAGES, DEALLOCATEEMSHANDLE
- ;-----------------------------------------------------------------------------
- FileAttr EQU 0 ;Swap file attribute (hidden+system)
- EmsPageSize EQU 16384 ;Size of EMS page
- FileBlockSize EQU 32768 ;Size of a file block
- StkSize EQU 128 ;Bytes in temporary stack
- lo EQU (WORD PTR 0) ;Convenient typecasts
- hi EQU (WORD PTR 2)
- ofst EQU (WORD PTR 0)
- segm EQU (WORD PTR 2)
- ;-----------------------------------------------------------------------------
- ;Variables in CS
- EmsDevice DB 'EMMXXXX0',0 ;Name of EMS device driver
- UsedEms DB 0 ;1 if swapping to EMS, 0 if to file
- BytesSwappedCS DD 0 ;Bytes to move during a swap
- EmsHandleCS DW 0 ;EMS handle
- FrameSegCS DW 0 ;Segment of EMS page window
- FileHandleCS DW 0 ;DOS file handle
- PrefixSegCS DW 0 ;Segment of base of program
- Status DW 0 ;ExecSwap status code
- LeftToSwap DD 0 ;Bytes left to move
- SaveSP DW 0 ;Original stack pointer
- SaveSS DW 0 ;Original stack segment
- PathPtr DD 0 ;Pointer to program to execute
- CmdPtr DD 0 ;Pointer to command line to execute
- ParasWeHave DW 0 ;Paragraphs allocated to process
- CmdLine DB 128 DUP(0) ;Terminated command line passed to DOS
- Path DB 64 DUP(0) ;Terminated path name passed to DOS
- FileBlock1 DB 16 DUP(0) ;FCB passed to DOS
- FileBlock2 DB 16 DUP(0) ;FCB passed to DOS
- BooBoo DB '$'
- ComeBack DB '$'
- EnvironSeg DW 0 ;Segment of environment for child
- CmdLinePtr DD 0 ;Pointer to terminated command line
- FilePtr1 DD 0 ;Pointer to FCB file
- FilePtr2 DD 0 ;Pointer to FCB file
- TempStack DB StkSize DUP(0) ;Temporary stack
- StackTop LABEL WORD ;Initial top of stack
- ;-----------------------------------------------------------------------------
- ;Macros
- MovSeg MACRO Dest,Src ;Set one segment register to another
- PUSH Src
- POP Dest
- ENDM
-
- MovMem MACRO Dest,Src ;Move from memory to memory via AX
- MOV AX,Src
- MOV Dest,AX
- ENDM
-
- InitSwapCount MACRO ;Initialize counter for bytes to swap
- MovMem LeftToSwap.lo,BytesSwappedCS.lo
- MovMem LeftToSwap.hi,BytesSwappedCS.hi
- ENDM
-
- SetSwapCount MACRO BlkSize ;Return CX = bytes to move this block
- LOCAL FullBlk ;...and reduce total bytes left to move
- MOV CX,BlkSize ;Assume we'll write a full block
- CMP LeftToSwap.hi,0 ;Is high word still non-zero?
- JNZ FullBlk ;Jump if so
- CMP LeftToSwap.lo,BlkSize ;Low word still a block or more?
- JAE FullBlk ;Jump if so
- MOV CX,LeftToSwap.lo ;Otherwise, move what's left
- FullBlk:SUB LeftToSwap.lo,CX ;Reduce number left to move
- SBB LeftToSwap.hi,0
- ENDM
-
- NextBlock MACRO SegReg, BlkSize ;Point SegReg to next block to move
- MOV AX,SegReg
- ADD AX,BlkSize/16 ;Add paragraphs to next segment
- MOV SegReg,AX ;Next block to move
- MOV AX,LeftToSwap.lo
- OR AX,LeftToSwap.hi ;Bytes left to move?
- ENDM
-
- EmsCall MACRO FuncAH ;Call EMM and prepare to check result
- MOV AH,FuncAH ;Set up function
- INT 67h
- OR AH,AH ;Error code in AH
- ENDM
-
- DosCallAH MACRO FuncAH ;Call DOS subfunction AH
- MOV AH,FuncAH
- INT 21h
- ENDM
-
- DosCallAX MACRO FuncAX ;Call DOS subfunction AX
- MOV AX,FuncAX
- INT 21h
- ENDM
-
- InitSwapFile MACRO
- MOV BX,FileHandleCS ;BX = handle of swap file
- XOR CX,CX
- XOR DX,DX ;Start of file
- DosCallAX 4200h ;DOS file seek
- ENDM
-
- HaltWithError MACRO Level ;Halt if non-recoverable error occurs
- PUSH CS
- POP DS
- MOV DX,OFFSET BooBoo
- MOV AH,9
- INT 21h
- MOV AL,Level ;Set errorlevel
- DosCallAH 4Ch
- ENDM
-
- MoveFast MACRO ;Move CX bytes from DS:SI to ES:DI
- CLD ;Forward
- RCR CX,1 ;Convert to words
- REP MOVSW ;Move the words
- RCL CX,1 ;Get the odd byte, if any
- REP MOVSB ;Move it
- ENDM
-
- SetTempStack MACRO ;Switch to temporary stack
- MOV AX,OFFSET StackTop ;Point to top of stack
- MOV BX,CS ;Temporary stack in this code segment
- CLI ;Interrupts off
- MOV SS,BX ;Change stack
- MOV SP,AX
- STI ;Interrupts on
- ENDM
- ;-----------------------------------------------------------------------------
- ;function ExecWithSwap(Path, CmdLine : string) : Word;
- EXECWITHSWAP PROC FAR
- PUSH BP
- MOV BP,SP ;Set up stack frame
-
- ;Move variables to CS where we can easily access them later
- MOV Status,1 ;Assume failure
- LES DI,[BP+6] ;ES:DI -> CmdLine
- MOV CmdPtr.ofst,DI
- MOV CmdPtr.segm,ES ;CmdPtr -> command line string
- LES DI,[BP+10] ;ES:DI -> Path
- MOV PathPtr.ofst,DI
- MOV PathPtr.segm,ES ;PathPtr -> path to execute
- MOV SaveSP,SP ;Save stack position
- MOV SaveSS,SS
- MovMem BytesSwappedCS.lo,_BytesSwapped.lo
- MovMem BytesSwappedCS.hi,_BytesSwapped.hi
- MovMem EmsHandleCS,_EmsHandle
- MovMem FrameSegCS,_FrameSeg
- MovMem FileHandleCS,_FileHandle
- MovMem PrefixSegCS,_PrefixSeg
- InitSwapCount ;Initialize bytes LeftToSwap
-
- ;Check for swapping to EMS or file
- CMP _EmsAllocated,0 ;Check flag for EMS method
- JZ NotEms ;Jump if EMS not used
- JMP WriteE ;Swap to EMS
- NotEms: CMP _FileAllocated,0 ;Check flag for swap file method
- JNZ WriteF ;Swap to file
- JMP ESDone ;Exit if no swapping method set
-
- ;Write to swap file
- WriteF: MovSeg DS,CS ;DS = CS
- InitSwapFile ;Seek to start of swap file
- JNC EF0 ;Jump if success
- JMP ESDone ;Exit if error
- EF0: SetSwapCount FileBlockSize ;CX = bytes to write
- MOV DX,OFFSET _FIRSTTOSAVE ;DS:DX -> start of region to save
- DosCallAH 40h ;File write
- JC EF1 ;Jump if write error
- CMP AX,CX ;All bytes written?
- JZ EF2 ;Jump if so
- EF1: JMP ESDone ;Exit if error
- EF2: NextBlock DS,FileBlockSize ;Point DS to next block to write
- JNZ EF0 ;Loop if bytes left to write
- MOV UsedEms,0 ;Flag we used swap file for swapping
- JMP SwapDone ;Done swapping out
-
- ;Write to EMS
- WriteE: MOV ES,_FrameSeg ;ES -> page window
- MOV DX,_EmsHandle ;DX = handle of our EMS block
- XOR BX,BX ;BX = initial logical page
- MovSeg DS,CS ;DS = CS
- EE0: XOR AL,AL ;Physical page 0
- EmsCall 44h ;Map physical page
- JZ EE1 ;Jump if success
- JMP ESDone ;Exit if error
- EE1: SetSwapCount EmsPageSize ;CX = Bytes to move
- XOR DI,DI ;ES:DI -> base of EMS page
- MOV SI,OFFSET _FIRSTTOSAVE ;DS:SI -> region to save
- MoveFast ;Move CX bytes from DS:SI to ES:DI
- INC BX ;Next logical page
- NextBlock DS,EmsPageSize ;Point DS to next page to move
- JNZ EE0 ;Loop if bytes left to move
- MOV UsedEms,1 ;Flag we used EMS for swapping
-
- ;Shrink memory allocated to this process
- SwapDone:MOV AX,PrefixSegCS
- MOV ES,AX ;ES = segment of our memory block
- DEC AX
- MOV DS,AX ;DS = segment of memory control block
- MOV CX,DS:[0003h] ;CX = current paragraphs owned
- MOV ParasWeHave,CX ;Save current paragraphs owned
- SetTempStack ;Switch to temporary stack
- MOV AX,OFFSET _FIRSTTOSAVE+15
- MOV CL,4
- SHR AX,CL ;Convert offset to paragraphs
- ADD BX,AX
- SUB BX,PrefixSegCS ;BX = new paragraphs to keep
- DosCallAH 4Ah ;SetBlock
- JNC EX0 ;Jump if successful
- JMP EX5 ;Swap back and exit
-
- ;Set up parameters and call DOS Exec
- EX0: MOV AX,ES:[002Ch] ;Get environment segment
- MOV EnvironSeg,AX
- MovSeg ES,CS ;ES = CS
- LDS SI,PathPtr ;DS:SI -> path to execute
- MOV DI,OFFSET Path ;ES:DI -> local ASCIIZ copy
- CLD
- ; LODSB ;Read current length
- ; CMP AL,63 ;Truncate if exceeds space set aside
- ; JB EX1
- ; MOV AL,63
- ;EX1: MOV CL,AL
- ; XOR CH,CH ;CX = bytes to copy
- MOV CX, 63
- REP MOVSB
- ; XOR AL,AL
- ; STOSB ;ASCIIZ terminate
- LDS SI,CmdPtr ;DS:SI -> Command line to pass
- MOV DI,OFFSET CmdLine ;ES:DI -> Local terminated copy
- ; LODSB
- ; CMP AL,126 ;Truncate command if exceeds space
- ; JB EX2
- ; MOV AL,126
- ;EX2: STOSB
- ; MOV CL,AL
- ; XOR CH,CH ;CX = bytes to copy
- MOV CX, 127
- REP MOVSB
- ; MOV AL,0DH ;Terminate with ^M
- ; STOSB
-
- MovSeg DS,CS ;DS = CS
- MOV SI,OFFSET CmdLine
- MOV CmdLinePtr.ofst,SI
- MOV CmdLinePtr.segm,DS ;Store pointer to command line
- ; INC SI
- MOV DI,OFFSET FileBlock1
- MOV FilePtr1.ofst,DI
- MOV FilePtr1.segm,ES ;Store pointer to filename 1, if any
- DosCallAX 2901h ;Parse FCB
- MOV DI,OFFSET FileBlock2
- MOV FilePtr2.ofst,DI
- MOV FilePtr2.segm,ES ;Store pointer to filename 2, if any
- DosCallAX 2901h ;Parse FCB
- MOV DX,OFFSET Path
- MOV BX,OFFSET EnvironSeg
- DosCallAX 4B00h ;Exec
- JC EX3 ;Jump if error in DOS call
- XOR AX,AX ;Return zero for success
- EX3: MOV Status,AX ;Save DOS error code
-
- ;Set up temporary stack and reallocate original memory block
- SetTempStack ;Set up temporary stack
- MOV ES,PrefixSegCS
- MOV BX,ParasWeHave
- DosCallAH 4Ah ;SetBlock
- JNC EX4 ;Jump if no error
- HaltWithError 0FFh ;Must halt if failure here
- EX4: InitSwapCount ;Initialize LeftToSwap
-
- ;Check which swap method is in use
- EX5: PUSH CS
- POP DS
- MOV DX,OFFSET ComeBack
- MOV AH,9
- INT 21h
- CMP UsedEms,0
- JZ ReadF ;Jump to read back from file
- JMP ReadE ;Read back from EMS
-
- ;Read back from swap file
- ReadF: MovSeg DS,CS ;DS = CS
- InitSwapFile ;Seek to start of swap file
- JNC EF3 ;Jump if we succeeded
- HaltWithError 0FEh ;Must halt if failure here
- EF3: SetSwapCount FileBlockSize ;CX = bytes to read
- MOV DX,OFFSET _FIRSTTOSAVE ;DS:DX -> start of region to restore
- DosCallAH 3Fh ;Read file
- JNC EF4 ;Jump if no error
- HaltWithError 0FEh ;Must halt if failure here
- EF4: CMP AX,CX
- JZ EF5 ;Jump if full block read
- HaltWithError 0FEh ;Must halt if failure here
- EF5: NextBlock DS,FileBlockSize ;Point DS to next page to read
- JNZ EF3 ;Jump if bytes left to read
- JMP ESDone ;We're done
-
- ;Copy back from EMS
- ReadE: MOV DS,FrameSegCS ;DS -> page window
- MOV DX,EmsHandleCS ;DX = handle of our EMS block
- XOR BX,BX ;BX = initial logical page
- MovSeg ES,CS ;ES = CS
- EE3: XOR AL,AL ;Physical page 0
- EmsCall 44h ;Map physical page
- JZ EE4 ;Jump if success
- HaltWithError 0FDh ;Must halt if failure here
- EE4: SetSwapCount EmsPageSize ;CX = Bytes to move
- XOR SI,SI ;DS:SI -> base of EMS page
- MOV DI,OFFSET _FIRSTTOSAVE ;ES:DI -> region to restore
- MoveFast ;Move CX bytes from DS:SI to ES:DI
- INC BX ;Next logical page
- NextBlock ES,EmsPageSize ;Point ES to next page to move
- JNZ EE3 ;Jump if so
-
- ESDone: CLI ;Switch back to original stack
- MOV SS,SaveSS
- MOV SP,SaveSP
- STI
- MOV AX,SEG DGROUP
- MOV DS,AX ;Restore DS
- MOV AX,Status ;Return status
- POP BP
- RET 8 ;Remove parameters and return
- EXECWITHSWAP ENDP
- ;-----------------------------------------------------------------------------
- ;Label marks first location to swap
- _FIRSTTOSAVE:
- ;-----------------------------------------------------------------------------
- ;function AllocateSwapFile : Boolean;
- ALLOCATESWAPFILE PROC FAR
- MOV CX,FileAttr ;Attribute for swap file
- MOV DX,OFFSET _SwapName ;DS:DX -> ASCIIZ swap name
- DosCallAH 3Ch ;Create file
- MOV _FileHandle,AX ;Save handle assuming success
- MOV AL,0 ;Assume failure
- JC ASDone ;Failed if carry set
- INC AL ;Return true for success
- ASDone: RET
- ALLOCATESWAPFILE ENDP
-
- ;-----------------------------------------------------------------------------
- ;procedure DeallocateSwapFile;
- DEALLOCATESWAPFILE PROC FAR
- MOV BX,_FileHandle ;Handle of swap file
- DosCallAH 3Eh ;Close file
- XOR CX,CX ;Normal attribute
- MOV DX,OFFSET _SwapName ;DS:DX -> ASCIIZ swap name
- DosCallAX 4301h ;Set file attribute
- DosCallAH 41h ;Delete file
- RET
- DEALLOCATESWAPFILE ENDP
-
- ;-----------------------------------------------------------------------------
- ;function EmsInstalled : Boolean;
- EMSINSTALLED PROC FAR
-
- PUSH DS
- MovSeg DS,CS ;DS = CS
- MOV DX,OFFSET EmsDevice ;DS:DX -> EMS driver name
- DosCallAX 3D02h ;Open for read/write
- POP DS
- MOV BX,AX ;Save handle in case one returned
- MOV AL,0 ;Assume FALSE
- JC EIDone
- DosCallAH 3Eh ;Close file
- MOV AL,1 ;Return TRUE
-
- EIDone: RET
-
- EMSINSTALLED ENDP
-
- ;-----------------------------------------------------------------------------
- ;function EmsPageFrame : Word;
- EMSPAGEFRAME PROC FAR
-
- EmsCall 41h ;Get page frame
- MOV AX,BX ;AX = segment
- JZ EPDone ;Done if Error = 0
- XOR AX,AX ;Else segment = 0
-
- EPDone: RET
-
- EMSPAGEFRAME ENDP
-
- ;-----------------------------------------------------------------------------
- ;function AllocateEmsPages(NumPages : Word) : Word;
- ALLOCATEEMSPAGES PROC FAR
-
- MOV BX,SP ;Set up stack frame
- MOV BX,SS:[BX+4] ;BX = NumPages
- EmsCall 43h ;Allocate EMS
- MOV AX,DX ;Assume success
- JZ APDone ;Done if not 0
- MOV AX,0FFFFh ;$FFFF for failure
-
- APDone: RET 2 ;Remove parameter and return
-
- ALLOCATEEMSPAGES ENDP
-
- ;-----------------------------------------------------------------------------
- ;procedure DeallocateEmsHandle(Handle : Word);
- DEALLOCATEEMSHANDLE PROC FAR
-
- MOV BX,SP ;Set up stack frame
- MOV DX,SS:[BX+4] ;DX = Handle
- EmsCall 45h ;Deallocate EMS
-
- RET 2 ;Remove parameter and return
-
- DEALLOCATEEMSHANDLE ENDP
-
- ;CODE ENDS
- END